package com.ranchuanyin.schoolcat.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.ranchuanyin.schoolcat.config.NettyConfig;
import com.ranchuanyin.schoolcat.domain.CatGroup;
import com.ranchuanyin.schoolcat.dto.MessageGroupDTO;
import com.ranchuanyin.schoolcat.dto.SendMessageDto;
import com.ranchuanyin.schoolcat.dto.WithdrawOneDTO;
import com.ranchuanyin.schoolcat.service.CatGroupService;
import com.ranchuanyin.schoolcat.service.PushService;
import com.ranchuanyin.schoolcat.util.ExecutorServiceUtil;
import com.ranchuanyin.schoolcat.util.RedisMessageUtil;
import com.ranchuanyin.schoolcat.vo.message.GroupMessagesVo;
import com.ranchuanyin.schoolcat.vo.message.ReceiveMessagesVo;
import com.ranchuanyin.schoolcat.vo.WithdrawMessagesVo;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;

@Service
public class PushServiceImpl implements PushService {
    @Resource
    RedisMessageUtil redisMessageUtil;
    @Resource
    CatGroupService catGroupService;


    @Override
    public Boolean pushMsgToOne(SendMessageDto sendMessageDto) {
        ConcurrentHashMap<String, Channel> userChannelMap = NettyConfig.getUserChannelMap();
        Channel channel = userChannelMap.get(sendMessageDto.getToUserId());
        ReceiveMessagesVo vo = new ReceiveMessagesVo();
        vo.setMessage(sendMessageDto.getMessage());
        vo.setToUserId(sendMessageDto.getToUserId());
        vo.setFromUserId(sendMessageDto.getFromUserId());
        vo.setMessageDate(DateUtil.now());
        vo.setUsername(sendMessageDto.getUsername());
        vo.setAvatar(sendMessageDto.getAvatar());
        vo.setType(sendMessageDto.getType());
        vo.setId(sendMessageDto.getId());
        if (Objects.isNull(channel)) {
            redisMessageUtil.addOfflineMessage(Long.valueOf(sendMessageDto.getToUserId()), vo);
            return false;
        }
        channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(vo)));
        return true;
    }

    @Override
    public void pushMsgToAll(String msg) {
        NettyConfig.getChannelGroup().writeAndFlush(new TextWebSocketFrame(msg));
    }

    @Override
    public void pushMsgToGroup(MessageGroupDTO dto) {
        CatGroup group = catGroupService.getById(dto.getGroupId());
        List<String> userIds = group.getUserIds();
        userIds.remove(dto.getMessageUserId());
        ConcurrentHashMap<String, Channel> userChannelMap = NettyConfig.getUserChannelMap();

        // 创建任务列表
        List<Callable<Void>> tasks = new ArrayList<>();
        for (String id : userIds) {
            tasks.add(() -> {
                Channel channel = userChannelMap.get(id);
                GroupMessagesVo vo = new GroupMessagesVo();
                // 设置vo的属性
                vo.setId(dto.getId());
                vo.setFromUserId(dto.getGroupId());
                vo.setMessageUserId(id);
                vo.setUsername(dto.getUsername());
                vo.setMessage(dto.getMessage());
                vo.setMessageDate(DateUtil.now());
                vo.setMessageUser(dto.getMessageUser());
                vo.setAvatar(dto.getAvatar());
                vo.setType(dto.getType());

                if (Objects.isNull(channel)) {
                    redisMessageUtil.addOfflineMessage(Long.valueOf(id), vo);
                } else {
                    channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(vo)));
                }
                return null;
            });
        }

        // 使用工具类执行任务并等待完成，收集结果
        ExecutorServiceUtil.executeAndWaitForResults(tasks);
    }

    @Override
    public void WithdrawOne(WithdrawOneDTO dto) {
        ConcurrentHashMap<String, Channel> userChannelMap = NettyConfig.getUserChannelMap();
        char c = dto.getToUserId().charAt(0);
        if (c == 'G'){
            CatGroup group = catGroupService.getById(dto.getToUserId());
            List<String> userIds = group.getUserIds();
            userIds.remove(dto.getUserId());
            Channel channel = null;
            WithdrawMessagesVo vo = new WithdrawMessagesVo();
            vo.setId(dto.getMessageId());
            vo.setType(3);
            for (String id : userIds
            ) {
                channel = userChannelMap.get(id);
                if (Objects.isNull(channel)) {
                    redisMessageUtil.addOfflineMessage(Long.valueOf(id), vo);
                } else
                    channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(vo)));
            }
        }else {
            Channel channel = userChannelMap.get(dto.getToUserId());
            WithdrawMessagesVo vo = new WithdrawMessagesVo();
            vo.setId(dto.getMessageId());
            vo.setType(3);
            if (Objects.isNull(channel)) {
                redisMessageUtil.addOfflineMessage(Long.valueOf(dto.getToUserId()), vo);
                return;
            }
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(vo)));
        }
    }

}

